﻿#pragma once
#include <dp/config.h>

#include <dp/sys/common.h>

DP_BEGIN

namespace {

	// An abstract struct used to hold a callee and its params.
	// calles are function or struct/class with parentheses operators.
	struct Bind 
	{
		virtual void operator () () = 0;
	};

	template<class O>
	struct Bind0 : public Bind
	{
		O &m_o;

		Bind0(O &o)
			: m_o(o) 
		{ 
		}

		virtual void operator () ()
		{
			m_o();
		}
	};

	template<class O, class T>
	struct Bind1 : public Bind
	{
		O &m_o;
		T m_t;

		Bind1(O &o, T t)
			: m_o(o)
			, m_t(t)
		{
		}

		virtual void operator () ()
		{
			m_o(m_t);
		}
	};

	template<class O, class T1, class T2>
	struct Bind2 : public Bind
	{
		O &m_o;
		T1 m_t1;
		T2 m_t2;

		Bind2(O &o, T1 t1, T2 t2)
			: m_o(o)
			, m_t1(t1)
			, m_t2(t2)
		{
		}

		virtual void operator () ()
		{
			m_o(m_t1, m_t2);
		}
	};

	template<class O, class T1, class T2, class T3>
	struct Bind3 : public Bind
	{
		O &m_o;
		T1 m_t1;
		T2 m_t2;
		T3 m_t3;

		Bind3(O &o, T1 t1, T2 t2, T3 t3) 
			: m_o(o)
			, m_t1(t1)
			, m_t2(t2)
			, m_t3(t3)
		{
		}

		virtual void operator () ()
		{
			m_o(m_t1, m_t2, m_t3);
		}
	};

	template<class O, class T1, class T2, class T3, class T4>
	struct Bind4 : public Bind
	{
		O &m_o;
		T1 m_t1;
		T2 m_t2;
		T3 m_t3;
		T4 m_t4;

		Bind4(O &o, T1 t1, T2 t2, T3 t3, T4 t4)
			: m_o(o)
			, m_t1(t1)
			, m_t2(t2)
			, m_t3(t3)
			, m_t4(t4)
		{
		}

		virtual void operator () ()
		{
			m_o(m_t1, m_t2, m_t3, m_t4);
		}
	};

	template<class O, class T1, class T2, class T3, class T4, class T5>
	struct Bind5 : public Bind
	{
		O &m_o;
		T1 m_t1;
		T2 m_t2;
		T3 m_t3;
		T4 m_t4;
		T5 m_t5;

		Bind5(O &o, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
			: m_o(o)
			, m_t1(t1)
			, m_t2(t2)
			, m_t3(t3)
			, m_t4(t4)
			, m_t5(t5)
		{
		}

		virtual void operator () ()
		{
			m_o(m_t1, m_t2, m_t3, m_t4, m_t5);
		}
	};
}

DP_END
